home *** CD-ROM | disk | FTP | other *** search
/ Games of Daze / Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso / djgpp / clients / xlsfonts / xlsfonts.c < prev    next >
C/C++ Source or Header  |  1994-08-12  |  15KB  |  617 lines

  1. /*
  2.  * $XConsortium: xlsfonts.c,v 1.32 91/06/24 11:09:12 gildea Exp $
  3.  *
  4.  * Copyright 1989 Massachusetts Institute of Technology
  5.  *
  6.  * Permission to use, copy, modify, and distribute this software and its
  7.  * documentation for any purpose and without fee is hereby granted, provided
  8.  * that the above copyright notice appear in all copies and that both that
  9.  * copyright notice and this permission notice appear in supporting
  10.  * documentation, and that the name of M.I.T. not be used in advertising
  11.  * or publicity pertaining to distribution of the software without specific,
  12.  * written prior permission.  M.I.T. makes no representations about the
  13.  * suitability of this software for any purpose.  It is provided "as is"
  14.  * without express or implied warranty.
  15.  *
  16.  * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
  17.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T.
  18.  * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  19.  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  20.  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 
  21.  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  22.  */
  23.  
  24. #include <X11/Xlib.h>
  25. #include <X11/Xutil.h>
  26. #include <stdio.h>
  27. #include "dsimple.h"
  28.  
  29. #define N_START 1000  /* Maximum # of fonts to start with */
  30.  
  31. int max_output_line_width = 79;
  32. int output_line_padding = 3;
  33. int columns = 0;
  34.  
  35. #define L_SHORT 0
  36. #define L_MEDIUM 1
  37. #define L_LONG 2
  38. #define L_VERYLONG 3
  39.  
  40. Bool    sort_output = True;
  41. Bool    open_instead_of_list = False;
  42. int    long_list = L_SHORT;
  43. int    nnames = N_START;
  44. int    font_cnt;
  45. int    min_max;
  46. typedef struct {
  47.     char        *name;
  48.     XFontStruct    *info;
  49. } FontList;
  50. FontList    *font_list;
  51.  
  52.  
  53. usage()
  54. {
  55.     fprintf (stderr,"usage:  %s [-options] [-fn pattern]\n", program_name);
  56.     fprintf (stderr, "where options include:\n");
  57.     fprintf (stderr,
  58.     "    -l[l[l]]                 give long info about each font\n");
  59.     fprintf (stderr,
  60.     "    -m                       give character min and max bounds\n");
  61.     fprintf (stderr,
  62.     "    -C                       force columns\n");
  63.     fprintf (stderr,
  64.     "    -1                       force single column\n");
  65.     fprintf (stderr,
  66.     "    -u                       keep output unsorted\n");
  67.     fprintf (stderr,
  68.     "    -o                       use OpenFont/QueryFont instead of ListFonts\n");
  69.     fprintf (stderr,
  70.     "    -w width                 maximum width for multiple columns\n");
  71.     fprintf (stderr,
  72.     "    -n columns               number of columns if multi column\n");
  73.     fprintf (stderr,
  74.     "    -display displayname     X server to contact\n");
  75.     fprintf (stderr,
  76.         "\n");
  77.     exit(1);
  78. }
  79.  
  80. main(argc, argv)
  81. int argc;
  82. char **argv;    
  83. {
  84.     int    argcnt = 0, i;
  85.  
  86.     INIT_NAME;
  87.  
  88.     /* Handle command line arguments, open display */
  89.     Setup_Display_And_Screen(&argc, argv);
  90.     for (argv++, argc--; argc; argv++, argc--) {
  91.         if (argv[0][0] == '-') {
  92.             if (argcnt > 0) usage ();
  93.             for (i=1; argv[0][i]; i++)
  94.                 switch(argv[0][i]) {
  95.                 case 'l':
  96.                     long_list++;
  97.                     break;
  98.                 case 'm':
  99.                     min_max++;
  100.                     break;
  101.                 case 'C':
  102.                     columns = 0;
  103.                     break;
  104.                 case '1':
  105.                     columns = 1;
  106.                     break;
  107.                 case 'f':
  108.                     if (--argc <= 0) usage ();
  109.                     argcnt++;
  110.                     argv++;
  111.                     get_list(argv[0]);
  112.                     goto next;
  113.                 case 'w':
  114.                     if (--argc <= 0) usage ();
  115.                     argv++;
  116.                     max_output_line_width = atoi(argv[0]);
  117.                     goto next;
  118.                 case 'n':
  119.                     if (--argc <= 0) usage ();
  120.                     argv++;
  121.                     columns = atoi(argv[0]);
  122.                     goto next;
  123.                 case 'o':
  124.                     open_instead_of_list = True;
  125.                     break;
  126.                 case 'u':
  127.                     sort_output = False;
  128.                     break;
  129.                 default:
  130.                     usage();
  131.                     break;
  132.                 }
  133.             if (i == 1)
  134.                 usage();
  135.         } else {
  136.             argcnt++;
  137.             get_list(argv[0]);
  138.         }
  139.       next: ;
  140.     }
  141.     if (argcnt == 0)
  142.         get_list("*");
  143.     show_fonts();
  144.     exit(0);
  145. }
  146.  
  147. get_list(pattern)
  148.     char    *pattern;
  149. {
  150.     int    available = nnames+1,
  151.         i;
  152.     char    **fonts;
  153.     XFontStruct    *info;
  154.  
  155.     /* Get list of fonts matching pattern */
  156.     for (;;) {
  157.         if (open_instead_of_list) {
  158.             info = XLoadQueryFont (dpy, pattern);
  159.  
  160.             if (info) {
  161.             fonts = &pattern;
  162.             available = 1;
  163.             XUnloadFont (dpy, info->fid);
  164.             } else {
  165.             fonts = NULL;
  166.             }
  167.             break;
  168.         }
  169.             
  170.         if (long_list == L_MEDIUM)
  171.             fonts = XListFontsWithInfo(dpy,
  172.                 pattern, nnames, &available, &info);
  173.         else
  174.             fonts = XListFonts(dpy, pattern, nnames, &available);
  175.         if (fonts == NULL || available < nnames)
  176.             break;
  177.         if (long_list == L_MEDIUM)
  178.             XFreeFontInfo(fonts, info, available);
  179.         else
  180.             XFreeFontNames(fonts);
  181.         nnames = available * 2;
  182.     }
  183.  
  184.     if (fonts == NULL) {
  185.         fprintf(stderr, "%s: pattern \"%s\" unmatched\n",
  186.             program_name, pattern);
  187.         return;
  188.     }
  189.  
  190.     font_list = (FontList *)Realloc((char *)font_list,
  191.         (font_cnt + available) * sizeof(FontList));
  192.     for (i=0; i<available; i++) {
  193.         font_list[font_cnt].name = fonts[i];
  194.         if (long_list == L_MEDIUM)
  195.             font_list[font_cnt].info = info + i;
  196.         else
  197.             font_list[font_cnt].info = NULL;
  198.         font_cnt++;
  199.     }
  200. }
  201.  
  202. compare(f1, f2)
  203.     FontList    *f1, *f2;
  204. {
  205.     char    *p1 = f1->name,
  206.         *p2 = f2->name;
  207.  
  208.     while (*p1 && *p2 && *p1 == *p2)
  209.         p1++, p2++;
  210.     return(*p1 - *p2);
  211. }
  212.  
  213. show_fonts()
  214. {
  215.     int    i;
  216.  
  217.     if (font_cnt == 0)
  218.         return;
  219.  
  220.     /* first sort the output */
  221.     if (sort_output) qsort(font_list, font_cnt, sizeof(FontList), compare);
  222.  
  223.     if (long_list > L_MEDIUM) {
  224.         for (i = 0; i < font_cnt; i++) {
  225.         do_query_font (dpy, font_list[i].name);
  226.         }
  227.         return;
  228.     }
  229.  
  230.     if (long_list == L_MEDIUM) {
  231.         XFontStruct    *pfi;
  232.         char        *string;
  233.  
  234.         printf("DIR  ");
  235.         printf("MIN  ");
  236.         printf("MAX ");
  237.         printf("EXIST ");
  238.         printf("DFLT ");
  239.         printf("PROP ");
  240.         printf("ASC ");
  241.         printf("DESC ");
  242.         printf("NAME");
  243.         printf("\n");
  244.         for (i=0; i<font_cnt; i++) {
  245.             pfi = font_list[i].info;
  246.             if (!pfi) {
  247.                 fprintf (stderr, 
  248.                      "%s:  no font information for font \"%s\".\n",
  249.                      program_name, 
  250.                      font_list[i].name ? 
  251.                      font_list[i].name : "");
  252.                 continue;
  253.             }
  254.             switch(pfi->direction) {
  255.             case FontLeftToRight: string = "-->"; break;
  256.             case FontRightToLeft: string = "<--"; break;
  257.             default:          string = "???"; break;
  258.             }
  259.             printf("%-4s", string);
  260.             if (pfi->min_byte1 == 0
  261.              && pfi->max_byte1 == 0) {
  262.                 printf(" %3d ", pfi->min_char_or_byte2);
  263.                 printf(" %3d ", pfi->max_char_or_byte2);
  264.             } else {
  265.                 printf("*%3d ", pfi->min_byte1);
  266.                 printf("*%3d ", pfi->max_byte1);
  267.             }
  268.             printf("%5s ", pfi->all_chars_exist ? "all" : "some");
  269.             printf("%4d ", pfi->default_char);
  270.             printf("%4d ", pfi->n_properties);
  271.             printf("%3d ", pfi->ascent);
  272.             printf("%4d ", pfi->descent);
  273.             printf("%s\n", font_list[i].name);
  274.             if (min_max) {
  275.                 char    min[ BUFSIZ ],
  276.                     max[ BUFSIZ ];
  277.                 char    *pmax = max,
  278.                     *pmin = min;
  279.  
  280.                 strcpy(pmin, "     min(l,r,w,a,d) = (");
  281.                 strcpy(pmax, "     max(l,r,w,a,d) = (");
  282.                 pmin += strlen(pmin);
  283.                 pmax += strlen(pmax);
  284.  
  285.                 copy_number(&pmin, &pmax,
  286.                     pfi->min_bounds.lbearing,
  287.                     pfi->max_bounds.lbearing);
  288.                 *pmin++ = *pmax++ = ',';
  289.                 copy_number(&pmin, &pmax,
  290.                     pfi->min_bounds.rbearing,
  291.                     pfi->max_bounds.rbearing);
  292.                 *pmin++ = *pmax++ = ',';
  293.                 copy_number(&pmin, &pmax,
  294.                     pfi->min_bounds.width,
  295.                     pfi->max_bounds.width);
  296.                 *pmin++ = *pmax++ = ',';
  297.                 copy_number(&pmin, &pmax,
  298.                     pfi->min_bounds.ascent,
  299.                     pfi->max_bounds.ascent);
  300.                 *pmin++ = *pmax++ = ',';
  301.                 copy_number(&pmin, &pmax,
  302.                     pfi->min_bounds.descent,
  303.                     pfi->max_bounds.descent);
  304.                 *pmin++ = *pmax++ = ')';
  305.                 *pmin = *pmax = '\0';
  306.                 printf("%s\n", min);
  307.                 printf("%s\n", max);
  308.             }
  309.         }
  310.         return;
  311.     }
  312.  
  313.     if ((columns == 0 && isatty(1)) || columns > 1) {
  314.         int    width,
  315.             max_width = 0,
  316.             lines_per_column,
  317.             j,
  318.             index;
  319.  
  320.         for (i=0; i<font_cnt; i++) {
  321.             width = strlen(font_list[i].name);
  322.             if (width > max_width)
  323.                 max_width = width;
  324.         }
  325.         if (max_width == 0)
  326.             Fatal_Error("all %d fontnames listed are zero length",
  327.                     font_cnt);
  328.  
  329.         if (columns == 0) {
  330.             if ((max_width * 2) + output_line_padding >
  331.             max_output_line_width) {
  332.             columns = 1;
  333.             } else {
  334.             max_width += output_line_padding;
  335.             columns = ((max_output_line_width +
  336.                     output_line_padding) / max_width);
  337.             }
  338.         } else {
  339.             max_width += output_line_padding;
  340.         }
  341.         if (columns <= 1) goto single_column;
  342.  
  343.         if (font_cnt < columns)
  344.             columns = font_cnt;
  345.         lines_per_column = (font_cnt + columns - 1) / columns;
  346.  
  347.         for (i=0; i<lines_per_column; i++) {
  348.             for (j=0; j<columns; j++) {
  349.                 index = j * lines_per_column + i;
  350.                 if (index >= font_cnt)
  351.                     break;
  352.                 if (j+1 == columns)
  353.                     printf("%s", font_list[ index ].name);
  354.                 else
  355.                     printf("%-*s",
  356.                         max_width, 
  357.                         font_list[ index ].name);
  358.             }
  359.             printf("\n");
  360.         }
  361.         return;
  362.     }
  363.  
  364.       single_column:
  365.     for (i=0; i<font_cnt; i++)
  366.         printf("%s\n", font_list[i].name);
  367. }
  368.  
  369. max(i, j)
  370.     int    i, j;
  371. {
  372.     if (i > j)
  373.         return (i);
  374.     return(j);
  375. }
  376.  
  377. copy_number(pp1, pp2, n1, n2)
  378.     char    **pp1, **pp2;
  379.     int    n1, n2;
  380. {
  381.     char    *p1 = *pp1;
  382.     char    *p2 = *pp2;
  383.     int    w;
  384.  
  385.     sprintf(p1, "%d", n1);
  386.     sprintf(p2, "%d", n2);
  387.     w = max(strlen(p1), strlen(p2));
  388.     sprintf(p1, "%*d", w, n1);
  389.     sprintf(p2, "%*d", w, n2);
  390.     p1 += strlen(p1);
  391.     p2 += strlen(p2);
  392.     *pp1 = p1;
  393.     *pp2 = p2;
  394. }
  395.  
  396.  
  397.  
  398. /* ARGSUSED */
  399. static int IgnoreError(disp, event)
  400.     Display *disp;
  401.     XErrorEvent *event;
  402. {
  403.     return 0;
  404. }
  405.  
  406. static char *bounds_metrics_title =
  407.                       "width left  right  asc  desc   attr   keysym\n";
  408. static char *char_metrics_fmt = 
  409. "\t0x%02x%02x (%u)\t%4d  %4d  %4d  %4d  %4d  0x%04x  %s\n";
  410. static char *bounds_metrics_fmt =
  411. "\t%3s\t\t%4d  %4d  %4d  %4d  %4d  0x%04x\n";
  412.  
  413.  
  414. #define PrintBounds(_what,_ptr) \
  415. {   register XCharStruct *p = (_ptr); \
  416.     printf (bounds_metrics_fmt, _what, p->width, p->lbearing, \
  417.       p->rbearing, p->ascent, p->descent, p->attributes); }
  418.  
  419.  
  420. static char* stringValued [] = { /* values are atoms */
  421.     "FAMILY_NAME",
  422.     "FOUNDRY",
  423.     "STYLE",
  424.     "MONOSPACED",
  425.     "RELATIVE_WEIGHT",
  426.     "RELATIVE_SET",
  427.     "CLASSIFICATION",
  428.     "CHARSET_REGISTRY",
  429.     "CHARSET_ENCODING",
  430.     "QUALITY",
  431.     "CHARSET_COLLECTIONS",
  432.     "FULL_NAME",
  433.     "COPYRIGHT",
  434.     "WEIGHT_NAME",
  435.     "SETWIDTH_NAME",
  436.     "SLANT",
  437.     "SPACING",
  438.     "ADD_STYLE_NAME",
  439.     "FONTNAME_REGISTRY",
  440.     "FONT",
  441.     "DEVICE_FONT_NAME",
  442.      NULL
  443.     };
  444.  
  445. static void PrintProperty (prop)
  446.     XFontProp *prop;
  447. {
  448.     char *atom, *value;
  449.     char nosuch[40];
  450.     int i;
  451.     int (*oldhandler)() = XSetErrorHandler (IgnoreError);
  452.  
  453.     atom = XGetAtomName(dpy, prop->name);
  454.     if (!atom) {
  455.     atom = nosuch;
  456.     nosuch[0] = '\0';
  457.     (void)sprintf (atom, "No such atom = %d", prop->name);
  458.     }
  459.     printf ("      %s", atom);
  460.     for (i = strlen(atom); i < 22; i++) printf (" ");
  461.     for (i = 0; ; i++) {
  462.     if (stringValued[i] == NULL) {
  463.         printf ("%d\n", prop->card32);
  464.         break;
  465.     }
  466.     if (strcmp(stringValued[i], atom) == 0) {
  467.         value = XGetAtomName(dpy, prop->card32);
  468.         if (value == NULL)
  469.         printf ("%d (expected string value)\n", prop->card32);
  470.         else {
  471.         printf ("%s\n", value);
  472.         XFree (value);
  473.         }
  474.         break;
  475.     }
  476.     } 
  477.     if (atom != nosuch) XFree (atom);
  478.     XSetErrorHandler (oldhandler);
  479. }
  480.  
  481.  
  482. ComputeFontType (fs)
  483.     XFontStruct *fs;
  484. {
  485.     int i;
  486.     Bool char_cell = True;
  487.     char *reason = NULL;
  488.     XCharStruct *cs;
  489.     Atom awatom = XInternAtom (dpy, "AVERAGE_WIDTH", False);
  490.  
  491.     printf ("  font type:\t\t");
  492.     if (fs->min_bounds.width != fs->max_bounds.width) {
  493.     printf ("Proportional (min and max widths not equal)\n");
  494.     return;
  495.     }
  496.  
  497.     if (awatom) {
  498.     for (i = 0; i < fs->n_properties; i++) {
  499.         if (fs->properties[i].name == awatom &&
  500.         (fs->max_bounds.width * 10) != fs->properties[i].card32) {
  501.         char_cell = False;
  502.         reason = "font width not equal to AVERAGE_WIDTH";
  503.         break;
  504.         }
  505.     }
  506.     }
  507.  
  508.     if (fs->per_char) {
  509.     for (i = fs->min_char_or_byte2, cs = fs->per_char;
  510.          i <= fs->max_char_or_byte2; i++, cs++) {
  511.         if (cs->width == 0) continue;
  512.         if (cs->width != fs->max_bounds.width) {
  513.         /* this shouldn't happen since we checked above */
  514.         printf ("Proportional (characters not all the same width)\n");
  515.         return;
  516.         }
  517.         if (char_cell) {
  518.         if (cs->width < 0) {
  519.             if (!(cs->width <= cs->lbearing &&
  520.               cs->lbearing <= cs->rbearing &&
  521.               cs->rbearing <= 0)) {
  522.             char_cell = False;
  523.             reason = "ink outside bounding box";
  524.             }
  525.         } else {
  526.             if (!(0 <= cs->lbearing &&
  527.               cs->lbearing <= cs->rbearing &&
  528.               cs->rbearing <= cs->width)) {
  529.             char_cell = False;
  530.             reason = "ink outside bounding box";
  531.             }
  532.         }
  533.         if (!(cs->ascent <= fs->ascent &&
  534.               cs->descent <= fs->descent)) {
  535.             char_cell  = False;
  536.             reason = "characters not all same ascent or descent";
  537.         }
  538.         }
  539.     }
  540.     }
  541.  
  542.     printf ("%s", char_cell ? "Character Cell" : "Monospaced");
  543.     if (reason) printf (" (%s)", reason);
  544.     printf ("\n");
  545.     
  546.     return;
  547. }
  548.  
  549.  
  550. print_character_metrics (info)
  551.     register XFontStruct *info;
  552. {
  553.     register XCharStruct *pc = info->per_char;
  554.     register int i, j;
  555.     unsigned n, saven;
  556.  
  557.     printf ("  character metrics:\n");
  558.     saven = ((info->min_byte1 << 8) | info->min_char_or_byte2);
  559.     for (j = info->min_byte1; j <= info->max_byte1; j++) {
  560.     n = saven;
  561.     for (i = info->min_char_or_byte2; i <= info->max_char_or_byte2; i++) {
  562.         char *s = XKeysymToString ((KeySym) n);
  563.         printf (char_metrics_fmt, j, i, n, pc->width, pc->lbearing,
  564.             pc->rbearing, pc->ascent, pc->descent, pc->attributes,
  565.             s ? s : ".");
  566.         pc++;
  567.         n++;
  568.     }
  569.     saven += 256;
  570.     }
  571. }
  572.  
  573.  
  574. do_query_font (dpy, name)
  575.     Display *dpy;
  576.     char *name;
  577. {
  578.     register int i;
  579.     register XFontStruct *info = XLoadQueryFont (dpy, name);
  580.  
  581.     if (!info) {
  582.     fprintf (stderr, "%s:  unable to get info about font \"%s\"\n",
  583.          program_name, name);
  584.     return;
  585.     }
  586.     printf ("name:  %s\n", name ? name : "(nil)");
  587.     printf ("  direction:\t\t%s\n", ((info->direction == FontLeftToRight)
  588.                      ? "left to right" : "right to left"));
  589.     printf ("  indexing:\t\t%s\n", 
  590.         ((info->min_byte1 == 0 && info->max_byte1 == 0) ? "linear" :
  591.          "matrix"));
  592.     printf ("  rows:\t\t\t0x%02x thru 0x%02x (%d thru %d)\n",
  593.         info->min_byte1, info->max_byte1,
  594.         info->min_byte1, info->max_byte1);
  595.     printf ("  columns:\t\t0x%02x thru 0x%02x (%d thru %d)\n",
  596.         info->min_char_or_byte2, info->max_char_or_byte2,
  597.         info->min_char_or_byte2, info->max_char_or_byte2);
  598.     printf ("  all chars exist:\t%s\n",
  599.     (info->all_chars_exist) ? "yes" : "no");
  600.     printf ("  default char:\t\t0x%04x (%d)\n",
  601.         info->default_char, info->default_char);
  602.     printf ("  ascent:\t\t%d\n", info->ascent);
  603.     printf ("  descent:\t\t%d\n", info->descent);
  604.     ComputeFontType (info);
  605.     printf ("  bounds:\t\t%s", bounds_metrics_title);
  606.     PrintBounds ("min", &info->min_bounds);
  607.     PrintBounds ("max", &info->max_bounds);
  608.     if (info->per_char && long_list >= L_VERYLONG) 
  609.       print_character_metrics (info);
  610.     printf ("  properties:\t\t%d\n", info->n_properties);
  611.     for (i = 0; i < info->n_properties; i++)
  612.     PrintProperty (&info->properties[i]);
  613.     printf ("\n");
  614.  
  615.     XFreeFontInfo (NULL, info, 1);
  616. }
  617.